render hooks パターン
状態とコンポーネントを両方渡す時に便利
↑のLINE証券の記事でuhyo氏がこのパターンを命名してくれたおかげで、ググりやすくなった
これ以前でも、hooksからelement返すのはやったことある人は多分いると思うから起源は分からん
起源は追わなくてもいいかなと思う
命名してくれたことが偉いと思う
例
hooksとして状態を提供したいが、
その状態の操作はコンポーネント経由で行いたいに時に便利
さらに、状態の操作をコンポーネント経由のみに強制したいとか
このケースが一番起こりやすそう
複数のページから再利用されうるモーダルとか?
とおもったが、jotai使っとけばそもそもステートとコンポーネント別々に提供はできるんよなあ なんか必要なケースが思いつかなくなってきたmiyamonz.icon
useStateのように呼ばれた場所でだけステートを持つが、一方でコンポーネントも提供したい時、だろうか
code:js
const App: React.FC = () => {
return (
<div>
{renderChecks()}
<p>
<button disabled={!isAllChecked}>次へ</button>
</p>
</div>
)
}
twitterで検索すると、このパターンに対して不安を感じる声がある
hooksは単なる関数であり、ReactElementは単なるJSのオブジェクトに過ぎないので何も問題ない
不安を覚えるなら、そもそもJavaScriptでUIを構築することに不安を覚えても良いのでは?
hooksライブラリからコンポーネントを返したいことはあんまりないので、ライブラリにて採用されてる実例は少ない
このパターンを利用すべきケースは、ライブラリじゃなくてアプリケーション側のほうが発生しやすいと思われる
Element(ReactNode)を返すべきかFC ( ()=>Element)を返すべきか
@uhyo_: 「hooksからコンポーネントを返す」と言われたときにReact.FCを返すやつとJSX.Elementを返すやつが混同されている懸念がある。ぼくが推してるのはJSX.Elementを返すほうです(?) @uhyo_: React.FCを返すほうはあまり良くないと思う。というのもステートを内包させると必然的にステートが変わると別の関数オブジェクトになり、再レンダリング時にパフォーマンスのペナルティがあるから🫐 たしかにmiyamonz.icon
でもLINE証券の記事では後者なんだな
Element直返しで良いと思ってるが、何か後から渡す引数があるなら、(arg)=>Elementでもいいだろう
ここでのコンポーネントの受け渡しはReactNode単位が基本になるので、それとも合わせてElementで持つ方がいいだろう
ここで紹介されてるreact-hooks-use-modalもこのパターンと言える
こっちはFCを返してる
@uhyo_: そうだな。childrenは特殊な構文を与えられたrender propsであると考えたほうが幸せになりそう。レイアウトの責務を持つコンポーネントだとslotが1つだと普通に足りないときがあるし(?) そのとおりすぎて、childrenがReactNodeなのだから、別のpropにわたす変数もReactNode(Element)で保持して良いに決まってるmiyamonz.icon
そもそも、react elementを普段遣いのオブジェクトとして触りつつ、それを関数で返すようになると勝手にrender hooksになる
ただし厳密には、内部にuseState, useEffectなどが無いようなものは、hooksでは無く単なる関数で
コンポーネントレンダリング時にif文で分岐させてはいけない系の制約もなくなる
記事
fileのinput要素と、渡されたdataURLを返す
useStateのsetをコンポーネントとして受け取ると考えるとたしかにこれは良いか
値をユーザから受け取って、必要な情報を取り出すというロジックをrender hooks内に閉じ込められる、と考えられる
さらに、プレビュー画面もコンポーネントにしてしまうのも書いている